package body Storage_Streams.Bounded is

   procedure Clear (this : in out Bounded_Stream_Type)
   is
   begin
      this.F_Length := 0;
      this.Reset_For_Read;
      this.Reset_For_Write;
   end Clear;

   procedure Reset_For_Read (this : in out Bounded_Stream_Type)
   is
      pragma Inline (Reset_For_Read);
   begin
      this.F_Read_Index := 1;
   end Reset_For_Read;

   procedure Reset_For_Write (this : in out Bounded_Stream_Type)
   is
      pragma Inline (Reset_For_Write);
   begin
      this.F_Write_Index := 1;
   end Reset_For_Write;

   procedure Read (
      this : in out Bounded_Stream_Type;
      Item : out Stream_Element_Array;
      Last : out Stream_Element_Offset
      )
   is
      data : Stream_Element_Array 
      renames this.F_Data(this.F_Read_Index .. this.F_Length);
   begin
      if data'Length < Item'Length then
         Last := Item'First + data'Length - 1;
         Item(Item'First .. Last) := data;
         this.F_Read_Index := this.F_Read_Index + data'Length;
      else
         Last := Item'Last;
         Item := data(data'First .. data'First + Item'Length - 1);
         this.F_Read_Index := this.F_Read_Index + Item'Length;
      end if;
   end Read;

   procedure Write ( 
      this : in out Bounded_Stream_Type;
      Item : Stream_Element_Array 
      )
   is
      data : Stream_Element_Array
      renames this.F_Data(this.F_Write_Index .. this.F_Data'Last);
   begin
      if data'Length < Item'Length then
         raise Constraint_Error with "Out of stream capacity";
      else
         this.F_Length := data'First + Item'Length - 1;
         data(data'First .. this.F_Length) := Item;
         this.F_Write_Index := this.F_Write_Index + Item'Length;
      end if;
   end Write;

   function Read_Position (
      this : Bounded_Stream_Type 
      ) return Stream_Element_Offset
   is
      pragma Inline (Read_Position);
   begin
      return this.F_Read_Index;
   end Read_Position;

   function Write_Position (
      this : Bounded_Stream_Type 
      ) return Stream_Element_Offset
   is
      pragma Inline (Write_Position);
   begin
      return this.F_Write_Index;
   end Write_Position;


   procedure Set_Read_Position (
      this     : in out Bounded_Stream_Type;
      Position : Stream_Element_Offset
      )
   is
      pragma Inline(Set_Read_Position);
   begin
      if Position in 1 .. this.F_Data'Last + 1 then
         this.F_Read_Index := Position;
      else
         raise Constraint_Error with "Position out of range";
      end if;
   end Set_Read_Position;

   procedure Set_Write_Position (
      this     : in out Bounded_Stream_Type;
      Position : Stream_Element_Offset
      )
   is
      pragma Inline(Set_Write_Position);
   begin
      if Position in 1 .. this.F_Data'Last + 1 then
         this.F_Write_Index := Position;
      else
         raise Constraint_Error with "Position out of range";
      end if;
   end Set_Write_Position;

end Storage_Streams.Bounded;
